package simpleGeom;

public class MSegment {

	public int id;
	float x1;
	float y1;
	float z1;
	float x2;
	float y2;
	float z2;
	float vx;
	float vy;
	float vz;
	float c2;

	public float cX() {
		return (x1 + x2) * 0.5f;
	}


	public float cY() {
		return (y1 + y2) * 0.5f;
	}


	public float cZ() {
		return (z1 + z2) * 0.5f;
	}



	public float dX() {
		return x2 - x1;
	}

	public float dY() {
		return y2 - y1;
	}

	public float dZ() {
		return z2 - z1;
	}

	public float lengthSqr() {
		return dX() * dX() + dY() * dY() + dZ() * dZ();
	}

	public float length() {
		return (float) Math.sqrt(lengthSqr());
	}

	public void scale(float sX, float sY, float sZ) {
		x1 *= sX;
		x2 *= sX;
		y1 *= sY;
		y2 *= sY;
		z1 *= sZ;
		z2 *= sZ;
		reset();
	}

	public void translate(float tX, float tY, float tZ) {
		x1 += tX;
		x2 += tX;
		y1 += tY;
		y2 += tY;
		z1 += tZ;
		z2 += tZ;
		reset();
	}

	public MSegment(float x1, float y1, float z1, float x2, float y2, float z2) {
		this.x1 = x1;
		this.y1 = y1;
		this.z1 = z1;
		this.x2 = x2;
		this.y2 = y2;
		this.z2 = z2;
		reset();
	}

	public void reset() {
		vx = x2 - x1;
		vy = y2 - y1;
		vz = z2 - z1;
		c2 = dot(vx, vy, vz, vx, vy, vz);
	}

	public float dot(float x1, float y1, float z1, float x2, float y2,
			float z2) {
		return x1 * x2 + y1 * y2 + z1 * z2;
	}

	public float distSqr(float x1, float y1, float z1, float x2, float y2,
			float z2) {
		float dX = x2 - x1;
		float dY = y2 - y1;
		float dZ = z2 - z1;
		return dX * dX + dY * dY + dZ * dZ;
	}

	public float dist(float x1, float y1, float z1, float x2, float y2, float z2) {
		return (float) Math.sqrt(distSqr(x1, y1, z1, x2, y2, z2));
	}

	public float[] getClosestPtToSegment(float x, float y, float z) {

		float dx = x - x1;
		float dy = y - y1;
		float dz = z - z1;
		float c1 = dot(dx, dy, dz, vx, vy, vz);
		if (c1 <= 0)
			return new float[] { x1, y1, z1 };
		if (c2 <= c1)
			return new float[] { x2, y2, z2 };
		float b = c1 / c2;
		float px = x1 + b * vx;
		float py = y1 + b * vy;
		float pz = z1 + b * vz;
		return new float[] { px, py, pz };

	}

	// ===================================================================

	// dist_Point_to_Segment(): get the distance of a point to a segment
	// Input: a Point P and a Segment S (in any dimension)
	// Return: the shortest distance from P to S
	public float distToSegSqr(float x, float y, float z) {
		float dx = x - x1;
		float dy = y - y1;
		float dz = z - z1;
		float c1 = dot(dx, dy, dz, vx, vy, vz);
		if (c1 <= 0)
			return distSqr(x, y, z, x1, y1, z1);
		if (c2 <= c1)
			return distSqr(x, y, z, x2, y2, z2);
		float b = c1 / c2;
		float px = x1 + b * vx;
		float py = y1 + b * vy;
		float pz = z1 + b * vz;
		return distSqr(x, y, z, px, py, pz);
	}

	public float distToSeg(float x, float y, float z) {
		return (float) Math.sqrt(distToSegSqr(x, y, z));
	}

	public float distToLineSqr(float x, float y, float z) {
		float dx = x - x1;
		float dy = y - y1;
		float dz = z - z1;
		float c1 = dot(dx, dy, dz, vx, vy, vz);
		float b = c1 / c2;
		float px = x1 + b * vx;
		float py = y1 + b * vy;
		float pz = z1 + b * vz;
		return distSqr(x, y, z, px, py, pz);
	}

	public float distToLine(float x, float y, float z) {
		return (float) Math.sqrt(distToLineSqr(x, y, z));
	}

	public float x1() {
		return x1;
	}

	public void setX1(float x1) {
		this.x1 = x1;
		reset();
	}

	public float y1() {
		return y1;
	}

	public void setY1(float y1) {
		this.y1 = y1;
		reset();
	}

	public float z1() {
		return z1;
	}

	public void setZ1(float z1) {
		this.z1 = z1;
		reset();
	}

	public float x2() {
		return x2;
	}

	public void setX2(float x2) {
		this.x2 = x2;
		reset();
	}

	public float y2() {
		return y2;
	}

	public void setY2(float y2) {
		this.y2 = y2;
		reset();
	}

	public float z2() {
		return z2;
	}

	public void setZ2(float z2) {
		this.z2 = z2;
		reset();
	}

}
